package com.rou.im.framework.core.processorstack.impl;

import com.rou.im.framework.core.Request;
import com.rou.im.framework.core.Response;
import com.rou.im.framework.core.context.RequestContextHolder;
import com.rou.im.framework.core.processorstack.*;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * <p></p>
 *
 * @author GaoShuangWen
 * @since 2020-04-18 13:30
 */
public class DefaultProcessorStack implements ProcessorStack {

    private List<Processor> handlers;

    private TargetAction action;



    public DefaultProcessorStack(List<Processor> handlers,TargetAction action) {
        this.handlers = handlers;
        this.action = action;
    }

    public DefaultProcessorStack(TargetAction action) {
       this(new ArrayList<>(),action);
    }
    public DefaultProcessorStack() {
        this(null);
    }

    @Override
    public Response stack(Request request) {
        StackInvocation invocation = this.prepareInvocation(action);
        invocation.invoke(request);
        return RequestContextHolder.getContext().getResponse();
    }

    private StackInvocation prepareInvocation(TargetAction action) {
        return new StackInvocation() {
            final Iterator<Processor> iterator = handlers.iterator();

            @Override
            public void invoke(Request request) {
                if (iterator.hasNext()) {
                    iterator.next().process(request, this);
                } else {
                    action.execute(request);
                }
            }
        };
    }

    @Override
    public void addHandler(Processor handler) {
        handlers.add(handler);
    }

    @Override
    public void setAction(TargetAction action) {
        this.action = action;
    }


}
